<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>“妙文生花”</title>
    <!-- 引入外部资源 -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/GLTFLoader.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/OBJLoader.js"></script>
    <style>
        /* 全局样式 */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: "Microsoft YaHei", sans-serif;
        }

        body {
            background-color: #f5f7fa;
            padding: 20px;
        }

        /* 导航区样式 */
        .nav-container {
            max-width: 1400px;
            margin: 0 auto;
            text-align: center;
        }

        .nav-title {
            color: #2c3e50;
            margin-bottom: 60px;
            font-size: 2.5rem;
            background: linear-gradient(90deg, #3498db, #9b59b6);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }

        .function-container {
            display: flex;
            align-items: flex-start;
            justify-content: center;
            gap: 40px;
            margin: 0 auto;
            max-width: 1200px;
        }

        .function-item {
            position: relative;
            width: 100%;
            max-width: 280px;
            cursor: pointer;
        }

        .function-item:hover {
            transform: translateY(-10px) scale(1.03);
            transition: all 0.3s ease;
        }

        .function-card {
            background: white;
            border-radius: 15px;
            overflow: hidden;
            box-shadow: 0 10px 20px rgba(0,0,0,0.05);
            transition: all 0.3s ease;
        }

        .function-item:hover .function-card {
            box-shadow: 0 15px 30px rgba(52, 152, 219, 0.15);
        }

        .function-img-container {
            position: relative;
            height: 180px;
            overflow: hidden;
        }

        .function-img {
            width: 100%;
            height: 100%;
            object-fit: cover;
            transition: transform 0.5s ease;
        }

        .function-item:hover .function-img {
            transform: scale(1.1);
        }

        .function-overlay {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: linear-gradient(to bottom, 
                rgba(0,0,0,0) 0%, 
                rgba(0,0,0,0.2) 100%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .function-item:hover .function-overlay {
            opacity: 1;
        }

        .function-name {
            padding: 20px 15px 10px;
            color: #34495e;
            font-size: 18px;
            font-weight: 500;
            transition: color 0.3s ease;
            text-align: center;
        }

        .function-item:hover .function-name {
            color: #3498db;
        }

        .function-desc {
            font-size: 14px;
            color: #7f8c8d;
            padding: 0 15px 20px;
            line-height: 1.5;
            text-align: center;
            margin: 0;
        }

        .arrow {
            font-size: 3rem;
            color: #3498db;
            opacity: 0.7;
            transition: all 0.3s ease;
            animation: pulse 2s infinite;
            align-self: center;
        }

        .arrow:hover {
            opacity: 1;
            transform: scale(1.1);
        }

        @keyframes pulse {
            0% { transform: scale(1); }
            50% { transform: scale(1.1); }
            100% { transform: scale(1); }
        }

        /* 文生图功能区样式 */
        .text2img-container {
            display: none;
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            padding: 30px;
            border-radius: 15px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.1);
            animation: fadeIn 0.5s ease;
        }

        /* 3D模型查看器功能区 */
        .model-viewer-container {
            display: none;
            max-width: 1400px;
            margin: 0 auto;
            background: rgba(0, 0, 0, 0.7);
            border-radius: 15px;
            overflow: hidden;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
            animation: fadeIn 0.5s ease;
        }

        .ceshi-header {
            padding: 20px;
            background: rgba(0, 0, 0, 0.5);
            text-align: center;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        .ceshi-header h1 {
            font-size: 2.5rem;
            margin-bottom: 10px;
            background: linear-gradient(90deg, #ff8a00, #e52e71);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }
        
        .ceshi-subtitle {
            font-size: 1.1rem;
            opacity: 0.8;
            color: white;
        }
        
        .ceshi-content {
            display: flex;
            flex-direction: column;
            height: calc(100vh - 180px);
        }
        
        @media (min-width: 992px) {
            .ceshi-content {
                flex-direction: row;
            }
        }
        
        .ceshi-sidebar {
            width: 100%;
            background: rgba(20, 20, 30, 0.8);
            padding: 20px;
            overflow-y: auto;
        }
        
        @media (min-width: 992px) {
            .ceshi-sidebar {
                width: 300px;
                min-width: 300px;
            }
        }
        
        .ceshi-viewer-container {
            flex: 1;
            position: relative;
            background: #000;
        }
        
        #ceshi-model-viewer {
            width: 100%;
            height: 100%;
        }
        
        .ceshi-controls {
            position: absolute;
            bottom: 20px;
            left: 20px;
            display: flex;
            gap: 10px;
            z-index: 10;
        }
        
        .ceshi-control-btn {
            background: rgba(0, 0, 0, 0.7);
            color: white;
            border: none;
            border-radius: 50%;
            width: 50px;
            height: 50px;
            font-size: 1.2rem;
            cursor: pointer;
            transition: all 0.3s;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        
        .ceshi-control-btn:hover {
            background: rgba(50, 50, 150, 0.7);
            transform: scale(1.1);
        }
        
        .ceshi-folder-selector {
            margin-bottom: 20px;
        }
        
        .ceshi-folder-btn {
            display: block;
            width: 100%;
            padding: 12px;
            background: linear-gradient(90deg, #6a11cb 0%, #2575fc 100%);
            color: white;
            border: none;
            border-radius: 8px;
            font-size: 1rem;
            cursor: pointer;
            transition: all 0.3s;
            text-align: center;
        }
        
        .ceshi-folder-btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
        }

        .ceshi-image-upload {
            margin-bottom: 20px;
        }
        
        .ceshi-image-btn {
            display: block;
            width: 100%;
            padding: 12px;
            background: linear-gradient(90deg, #ff8a00, #e52e71);
            color: white;
            border: none;
            border-radius: 8px;
            font-size: 1rem;
            cursor: pointer;
            transition: all 0.3s;
            text-align: center;
        }
        
        .ceshi-image-btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
        }
        
        .ceshi-model-list {
            margin-top: 20px;
        }
        
        .ceshi-model-item {
            padding: 12px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 8px;
            margin-bottom: 10px;
            cursor: pointer;
            transition: all 0.3s;
            display: flex;
            align-items: center;
        }
        
        .ceshi-model-item:hover {
            background: rgba(255, 255, 255, 0.2);
            transform: translateX(5px);
        }
        
        .ceshi-model-item.active {
            background: rgba(74, 144, 226, 0.5);
            border-left: 4px solid #4a90e2;
        }
        
        .ceshi-model-icon {
            margin-right: 10px;
            font-size: 1.5rem;
        }
        
        .ceshi-model-info {
            flex: 1;
        }
        
        .ceshi-model-name {
            font-weight: bold;
            margin-bottom: 5px;
            color: white;
        }
        
        .ceshi-model-type {
            font-size: 0.8rem;
            opacity: 0.7;
            color: white;
        }
        
        .ceshi-loading {
            display: none;
            text-align: center;
            padding: 20px;
        }
        
        .ceshi-spinner {
            border: 5px solid rgba(255, 255, 255, 0.3);
            border-radius: 50%;
            border-top: 5px solid #4a90e2;
            width: 50px;
            height: 50px;
            animation: spin 1s linear infinite;
            margin: 0 auto 15px;
        }
        
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        
        .ceshi-no-models {
            text-align: center;
            padding: 20px;
            opacity: 0.7;
            color: white;
        }
        
        .ceshi-info-panel {
            position: absolute;
            top: 20px;
            right: 20px;
            background: rgba(0, 0, 0, 0.7);
            padding: 15px;
            border-radius: 8px;
            max-width: 300px;
            display: none;
            color: white;
            z-index: 10;
        }
        
        .ceshi-info-title {
            font-weight: bold;
            margin-bottom: 10px;
            color: #4a90e2;
        }
        
        .ceshi-close-info {
            position: absolute;
            top: 10px;
            right: 10px;
            background: none;
            border: none;
            color: white;
            cursor: pointer;
            font-size: 1.2rem;
        }
        
        .ceshi-footer {
            padding: 15px;
            text-align: center;
            background: rgba(0, 0, 0, 0.5);
            font-size: 0.9rem;
            opacity: 0.7;
            color: white;
        }

        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(20px); }
            to { opacity: 1; transform: translateY(0); }
        }

        .text2img-title {
            color: #2c3e50;
            font-size: 24px;
            margin-bottom: 20px;
            border-bottom: 2px solid #3498db;
            padding-bottom: 10px;
            position: relative;
            display: inline-block;
        }

        .text2img-title:hover::after {
            content: '';
            position: absolute;
            width: 0;
            height: 2px;
            bottom: -2px;
            left: 0;
            background-color: #2980b9;
            transition: width 0.3s ease;
            width: 100%;
        }

        .gallery {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 1.5rem;
            margin-top: 1rem;
        }
        .gallery-img {
            width: 100%;
            height: 256px;
            object-fit: contain;
            border: 1px solid #eee;
            border-radius: 4px;
        }
        .btn-primary {
            background-color: #3498db;
            border-color: #3498db;
        }
        .btn-primary:hover {
            background-color: #2980b9;
            border-color: #2980b9;
        }
        .btn-secondary {
            background-color: #95a5a6;
            color: white;
            border-color: #95a5a6;
        }
        .btn-secondary:hover {
            background-color: #7f8c8d;
            border-color: #7f8c8d;
        }
        .slider-group {
            margin-bottom: 1.5rem;
        }
        .text-muted {
            color: #7f8c8d !important;
        }

        .loading {
            display: none;
            border: 5px solid rgba(52, 152, 219, 0.1);
            border-top: 5px solid #3498db;
            border-radius: 50%;
            width: 50px;
            height: 50px;
            animation: spin 1s linear infinite;
            margin: 20px auto;
        }

        @keyframes shake {
            0%, 100% { transform: translateX(0); }
            10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
            20%, 40%, 60%, 80% { transform: translateX(5px); }
        }

        .back-btn {
            margin-top: 20px;
            background-color: #95a5a6;
            border-color: #95a5a6;
            color: white;
        }
        
        .back-btn:hover {
            background-color: #7f8c8d;
            border-color: #7f8c8d;
            color: white;
        }

        /* 语义分割结果页面样式 */
        .segmentation-container {
            display: none;
            max-width: 1400px;
            margin: 0 auto;
            background: white;
            padding: 30px;
            border-radius: 15px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.1);
            animation: fadeIn 0.5s ease;
        }
        
        .page-title {
            text-align: center;
            margin-bottom: 30px;
            color: #333;
        }
        
        .images-grid {
            display: flex;
            flex-wrap: wrap;
            justify-content: center;
            gap: 20px;
        }
        
        .image-card {
            background-color: white;
            padding: 15px;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
            text-align: center;
            max-width: 320px;
            cursor: pointer;
            transition: transform 0.3s ease;
        }
        
        .image-card:hover {
            transform: scale(1.05);
        }
        
        .seg-image {
            max-width: 100%;
            height: auto;
            border-radius: 4px;
        }

        /* 新增：图片详情页样式 */
        .image-detail-container {
            display: none;
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            padding: 30px;
            border-radius: 15px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.1);
            animation: fadeIn 0.5s ease;
            text-align: center;
        }
        
        .detail-image-container {
            margin: 30px auto;
            max-width: 800px;
            padding: 20px;
            background-color: #f9f9f9;
            border-radius: 10px;
        }
        
        .detail-image {
            max-width: 100%;
            height: auto;
            box-shadow: 0 4px 12px rgba(0,0,0,0.1);
            border-radius: 5px;
        }

        /* Yuyi页面样式 */
        .yuyi-container {
            display: none;
            max-width: 1400px;
            margin: 0 auto;
            padding: 30px;
            animation: fadeIn 0.5s ease;
        }

        @media (max-width: 992px) {
            .function-container {
                flex-direction: column;
                gap: 30px;
                align-items: center;
            }
            
            .arrow {
                transform: rotate(90deg);
                margin: 10px 0;
            }

            .function-item {
                max-width: 320px;
            }
        }
    </style>
</head>
<body>
    <!-- 导航区（默认显示） -->
    <div class="nav-container" id="navArea">
        <h1 class="nav-title">“妙文生花”</h1>
        <div class="function-container">
            <!-- 文生图图片按钮 -->
            <div class="function-item" onclick="showText2Img()">
                <div class="function-card">
                    <div class="function-img-container">
                        <img src="文生图需求.png" class="function-img" alt="文生图">
                        <div class="function-overlay"></div>
                    </div>
                    <p class="function-name">文生图</p>
                    <p class="function-desc">以 “用户输入” 为起点，分为两条并行分支 —— 一条是文本分支，依次经 “文本处理”“CLIP 编码”；另一条是边缘图分支，依次经 “边缘图输入”“Canny 检测”“边缘提取”。两条分支的结果共同输入 “Janus-Pro 生成” 环节，再经 “权重融合”“后处理”，最终实现 “输出展示”。</p>
                </div>
            </div>

            <div class="arrow">
                <i class="fa fa-long-arrow-right"></i>
            </div>

            <!-- 图生3D功能 -->
            <div class="function-item" onclick="showModelViewer()">
                <div class="function-card">
                    <div class="function-img-container">
                        <img src="生成图生 3D 主题图片.png" class="function-img" alt="图生3D">
                        <div class="function-overlay"></div>
                    </div>
                    <p class="function-name">图生3D</p>
                    <p class="function-desc">以 “输入层” 为起始点，先进入 “图像预处理层” 对输入内容开展前期处理；随后传递至 “3D 形状生成层” 以生成 3D 形状相关结果；接着经由 “模型后处理层” 对生成的 3D 模型进行后续优化等操作；最终通过 “输出层” 完成结果的输出。</p>
                </div>
            </div>

            <div class="arrow">
                <i class="fa fa-long-arrow-right"></i>
            </div>

            <!-- 语义分割功能 -->
            <div class="function-item" onclick="showSemanticSegmentation()">
                <div class="function-card">
                    <div class="function-img-container">
                        <img src="语义分割.png" class="function-img" alt="语义分割">
                        <div class="function-overlay"></div>
                    </div>
                    <p class="function-name">语义分割</p>
                    <p class="function-desc">以 “输入层” 接收优化后的 3D 网格模型为起点，进入 “特征提取层” 渲染多视角 2D 图像；随后通过 “分割执行层” 采用二维映射分割方案（基于 SAM、CLIPSeg 模型）完成部件拆分；再经 “后处理层” 修正分割边界、统一语义标签；最终通过 “输出展示层” 借助 Three.js 实现分割结果的交互式展示。</p>
                </div>
            </div>
        </div>
    </div>

    <!-- 文生图功能区 -->
    <div class="text2img-container" id="text2ImgArea">
        <h2 class="text2img-title">文生图功能（带Canny边缘控制）</h2>
        
        <div class="text2img-content">
            <p class="text-muted">提示：使用清晰详细的提示语可以获得更好的生成结果！Canny边缘图像可用于控制生成图像的轮廓。</p>

            <!-- 生成状态 -->
            <div class="mb-3">
                <label class="form-label">生成状态</label>
                <input type="text" id="statusMsg" class="form-control" value="就绪" disabled>
            </div>

            <!-- 第一行滑块：CFG权重 + 温度参数 -->
            <div class="row slider-group">
                <div class="col-md-6">
                    <label class="form-label">CFG权重</label>
                    <input type="range" id="cfgWeight" class="form-range" min="1" max="20" step="0.5" value="5">
                    <div class="text-end text-sm text-muted" id="cfgWeightValue">当前值：5.0</div>
                </div>
                <div class="col-md-6">
                    <label class="form-label">温度参数</label>
                    <input type="range" id="temperature" class="form-range" min="0.01" max="2.0" step="0.05" value="1.0">
                    <div class="text-end text-sm text-muted" id="temperatureValue">当前值：1.0</div>
                </div>
            </div>

            <!-- 第二行滑块：Canny低阈值 + Canny高阈值 -->
            <div class="row slider-group">
                <div class="col-md-6">
                    <label class="form-label">Canny低阈值</label>
                    <input type="range" id="cannyLow" class="form-range" min="1" max="255" step="1" value="100">
                    <div class="text-end text-sm text-muted" id="cannyLowValue">当前值：100</div>
                </div>
                <div class="col-md-6">
                    <label class="form-label">Canny高阈值</label>
                    <input type="range" id="cannyHigh" class="form-range" min="1" max="255" step="1" value="200">
                    <div class="text-end text-sm text-muted" id="cannyHighValue">当前值：200</div>
                </div>
            </div>

            <!-- 第三行：Canny图像上传 + 提示语文本框 -->
            <div class="row slider-group">
                <div class="col-md-4">
                    <label class="form-label">Canny控制图像（可选）</label>
                    <div class="card">
                        <div class="card-body text-center p-3" style="height: 180px; display: flex; align-items: center; justify-content: center;">
                            <img id="cannyPreview" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='%23dee2e6' viewBox='0 0 16 16'%3E%3Cpath d='M11 2.5a2.5 2.5 0 1 1 .603 1.628l-6.718 3.12a2.499 2.499 0 0 1 0 1.504l6.718 3.12a2.5 2.5 0 1 1-.488.876l-6.718-3.12a2.5 2.5 0 1 1 0-3.256l6.718-3.12A2.5 2.5 0 0 1 11 2.5z'/%3E%3C/svg%3E" 
                                class="img-fluid" alt="Canny图像预览">
                        </div>
                        <div class="card-footer p-2">
                            <input type="file" id="cannyImageInput" class="form-control form-control-sm" accept="image/*" onchange="previewCannyImage(event)">
                        </div>
                    </div>
                </div>
                <div class="col-md-8">
                    <label class="form-label">提示语</label>
                    <textarea id="promptInput" class="form-control" rows="3" placeholder="输入详细的图像描述..."></textarea>
                </div>
            </div>

            <!-- 第四行：随机种子 + 并行生成数量 -->
            <div class="row slider-group">
                <div class="col-md-4">
                    <label class="form-label">随机种子（可选）</label>
                    <input type="number" id="seedInput" class="form-control" placeholder="输入整数（留空则随机）" min="0">
                </div>
                <div class="col-md-8">
                    <label class="form-label">并行生成数量</label>
                    <input type="range" id="parallelSize" class="form-range" min="1" max="4" step="1" value="2">
                    <div class="text-end text-sm text-muted" id="parallelSizeValue">当前值：2</div>
                </div>
            </div>

            <!-- 按钮组：生成 + 清除 + 保存 -->
            <div class="row slider-group">
                <div class="col-md-4">
                    <button id="generateBtn" class="btn btn-primary w-100" onclick="showLoading()">生成图像</button>
                </div>
                <div class="col-md-4">
                    <button id="clearBtn" class="btn btn-secondary w-100" onclick="clearInputs()">清除输入</button>
                </div>
                <div class="col-md-4">
                    <button id="saveBtn" class="btn btn-secondary w-100" onclick="saveAllImages()">保存所有图像</button>
                </div>
            </div>

            <!-- 生成结果画廊 -->
            <div class="slider-group">
                <label class="form-label">生成结果</label>
                <div id="imageGallery" class="gallery">
                    <!-- 生成的图片将通过JS动态插入 -->
                </div>
            </div>

            <div class="loading" id="loadingIndicator"></div>
            
            <button class="back-btn btn btn-secondary" onclick="showNav()">返回工具导航</button>
        </div>
    </div>

    <!-- 3D模型查看器功能区 -->
    <div class="model-viewer-container" id="modelViewerArea">
        <header class="ceshi-header">
            <h1>图生3D模型展示</h1>
            <p class="ceshi-subtitle">选择包含3D模型的文件夹，浏览并交互式查看模型</p>
        </header>
        
        <div class="ceshi-content">
            <div class="ceshi-sidebar">
                <div class="ceshi-folder-selector">
                    <button class="ceshi-folder-btn" id="folder-btn">选择3D模型文件夹</button>
                    <input type="file" id="folder-input" webkitdirectory directory multiple style="display: none;">
                </div>
                
                <div class="ceshi-image-upload">
                    <button class="ceshi-image-btn" id="image-upload-btn">上传图片模式</button>
                    <input type="file" id="image-upload-input" accept="image/*" style="display: none;">
                </div>
                
                <div class="ceshi-loading" id="loading">
                    <div class="ceshi-spinner"></div>
                    <p>扫描文件夹中...</p>
                </div>
                
                <div class="ceshi-model-list" id="model-list">
                    <div class="ceshi-no-models" id="no-models">
                        请选择一个包含3D模型的文件夹
                    </div>
                </div>
            </div>
            
            <div class="ceshi-viewer-container">
                <div id="ceshi-model-viewer"></div>
                
                <div class="ceshi-controls">
                    <button class="ceshi-control-btn" id="reset-view" title="重置视图">↺</button>
                    <button class="ceshi-control-btn" id="toggle-rotate" title="自动旋转">⟳</button>
                    <button class="ceshi-control-btn" id="model-info" title="模型信息">ℹ</button>
                </div>
                
                <div class="ceshi-info-panel" id="info-panel">
                    <button class="ceshi-close-info" id="close-info">×</button>
                    <div class="ceshi-info-title">模型信息</div>
                    <div id="model-details">
                        选择模型查看详细信息
                    </div>
                </div>
            </div>
        </div>
        
        <footer class="ceshi-footer">
            <p>支持格式: OBJ, GLTF, GLB | 使用Three.js渲染引擎</p>
        </footer>
        
        <button class="back-btn btn btn-secondary" style="margin: 20px auto; display: block;" onclick="showNav()">返回工具导航</button>
    </div>

    <!-- 语义分割结果展示区 -->
    <div class="segmentation-container" id="segmentationArea">
        <h1 class="page-title">语义分割结果展示</h1>
        <div class="images-grid">
            <!-- 语义分割结果图片 -->
            <div class="image-card" onclick="showImageDetail('front.png', '正面视图')">
                <img src="front.png" alt="正面视图" class="seg-image">
            </div>
            <div class="image-card" onclick="showImageDetail('front_left.png', '左前视图')">
                <img src="front_left.png" alt="左前视图" class="seg-image">
            </div>
            <div class="image-card" onclick="showImageDetail('front_right.png', '右前视图')">
                <img src="front_right.png" alt="右前视图" class="seg-image">
            </div>
            <div class="image-card" onclick="showImageDetail('low_front.png', '前低视图')">
                <img src="low_front.png" alt="前低视图" class="seg-image">
            </div>
            <div class="image-card" onclick="showImageDetail('top_front.png', '前顶视图')">
                <img src="top_front.png" alt="前顶视图" class="seg-image">
            </div>
            <div class="image-card" onclick="showImageDetail('back.png', '后视图')">
                <img src="back.png" alt="后视图" class="seg-image">
            </div>
            <div class="image-card" onclick="showImageDetail('back_left.png', '左后视图')">
                <img src="back_left.png" alt="左后视图" class="seg-image">
            </div>
            <div class="image-card" onclick="showImageDetail('back_right.png', '右后视图')">
                <img src="back_right.png" alt="右后视图" class="seg-image">
            </div>
            <div class="image-card" onclick="showImageDetail('top_back.png', '后顶视图')">
                <img src="top_back.png" alt="后顶视图" class="seg-image">
            </div>
            <div class="image-card" onclick="showImageDetail('left.png', '左视图')">
                <img src="left.png" alt="左视图" class="seg-image">
            </div>
            <div class="image-card" onclick="showImageDetail('right.png', '右视图')">
                <img src="right.png" alt="右视图" class="seg-image">
            </div>
            <div class="image-card" onclick="showImageDetail('low_left.png', '左下视图')">
                <img src="low_left.png" alt="左下视图" class="seg-image">
            </div>
        </div>
        
        <button class="back-btn btn btn-secondary" style="margin: 20px auto; display: block;" onclick="showNav()">返回工具导航</button>
    </div>

    <!-- 新增：图片详情页 -->
    <div class="image-detail-container" id="imageDetailArea">
        <h1 class="page-title">语义分割图片详情</h1>
        <h3 id="detailImageTitle" class="mb-4"></h3>
        <div class="detail-image-container">
            <img id="detailImage" class="detail-image" src="" alt="">
        </div>
        <div class="mt-4">
            <button class="back-btn btn btn-secondary me-2" onclick="showSemanticSegmentation()">返回图片列表</button>
            <button class="btn btn-primary" onclick="saveCurrentImage()">保存图片</button>
        </div>
    </div>

    <!-- Yuyi页面 -->
    <div class="yuyi-container" id="yuyiArea">
        <h1 class="page-title">Yuyi 功能页面</h1>
        <div style="text-align: center; padding: 50px; background: white; border-radius: 15px; box-shadow: 0 5px 15px rgba(0,0,0,0.1);">
            <p style="font-size: 1.2rem; margin-bottom: 30px;">这是Yuyi功能的主页面。</p>
            <p style="color: #666;">可以在这里添加Yuyi相关的功能和内容</p>
        </div>
        
        <button class="back-btn btn btn-secondary" style="margin: 20px auto; display: block;" onclick="showSemanticSegmentation()">返回语义分割</button>
    </div>

    <script>
        // 获取区域元素
        const navArea = document.getElementById('navArea');
        const text2ImgArea = document.getElementById('text2ImgArea');
        const modelViewerArea = document.getElementById('modelViewerArea');
        const segmentationArea = document.getElementById('segmentationArea');
        const imageDetailArea = document.getElementById('imageDetailArea');
        const yuyiArea = document.getElementById('yuyiArea');
        const loadingIndicator = document.getElementById('loadingIndicator');
        const imageGallery = document.getElementById('imageGallery');
        const statusEl = document.getElementById('statusMsg');

        // 全局变量：存储当前查看的图片信息
        let currentImageSrc = '';
        let currentImageTitle = '';

        // 显示文生图功能区
        function showText2Img() {
            navArea.style.display = 'none';
            modelViewerArea.style.display = 'none';
            segmentationArea.style.display = 'none';
            imageDetailArea.style.display = 'none';
            yuyiArea.style.display = 'none';
            text2ImgArea.style.display = 'block';
            initSliderListeners();
            text2ImgArea.style.opacity = '0';
            setTimeout(() => {
                text2ImgArea.style.transition = 'opacity 0.5s ease';
                text2ImgArea.style.opacity = '1';
            }, 10);
        }

        // 显示3D模型查看器
        function showModelViewer() {
            navArea.style.display = 'none';
            text2ImgArea.style.display = 'none';
            segmentationArea.style.display = 'none';
            imageDetailArea.style.display = 'none';
            yuyiArea.style.display = 'none';
            modelViewerArea.style.display = 'block';
            modelViewerArea.style.opacity = '0';
            setTimeout(() => {
                modelViewerArea.style.transition = 'opacity 0.5s ease';
                modelViewerArea.style.opacity = '1';
                if (!window.ceshiSceneInitialized) {
                    initCeshiScene();
                    initCeshiEvents();
                    window.ceshiSceneInitialized = true;
                }
            }, 10);
        }

        // 显示语义分割结果
        function showSemanticSegmentation() {
            navArea.style.display = 'none';
            text2ImgArea.style.display = 'none';
            modelViewerArea.style.display = 'none';
            imageDetailArea.style.display = 'none';
            yuyiArea.style.display = 'none';
            segmentationArea.style.display = 'block';
            segmentationArea.style.opacity = '0';
            setTimeout(() => {
                segmentationArea.style.transition = 'opacity 0.5s ease';
                segmentationArea.style.opacity = '1';
            }, 10);
        }

        // 新增：显示图片详情页
        function showImageDetail(imageSrc, imageTitle) {
            // 保存当前图片信息
            currentImageSrc = imageSrc;
            currentImageTitle = imageTitle;
            
            // 更新详情页内容
            document.getElementById('detailImage').src = imageSrc;
            document.getElementById('detailImageTitle').textContent = imageTitle;
            
            // 显示详情页，隐藏列表页
            segmentationArea.style.display = 'none';
            imageDetailArea.style.display = 'block';
            imageDetailArea.style.opacity = '0';
            setTimeout(() => {
                imageDetailArea.style.transition = 'opacity 0.5s ease';
                imageDetailArea.style.opacity = '1';
            }, 10);
        }

        // 新增：保存当前查看的图片
        function saveCurrentImage() {
            if (!currentImageSrc) return;
            
            const a = document.createElement('a');
            a.href = currentImageSrc;
            const timestamp = new Date().toISOString().replace(/[-:\.T]/g, '').slice(0, 14);
            a.download = `segmentation-${timestamp}-${currentImageTitle}.png`;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            
            alert(`已保存图片: ${currentImageTitle}`);
        }

        // 显示Yuyi页面
        function showYuyiPage() {
            segmentationArea.style.display = 'none';
            imageDetailArea.style.display = 'none';
            yuyiArea.style.display = 'block';
            yuyiArea.style.opacity = '0';
            setTimeout(() => {
                yuyiArea.style.transition = 'opacity 0.5s ease';
                yuyiArea.style.opacity = '1';
            }, 10);
        }

        // 显示导航区
        function showNav() {
            if (text2ImgArea.style.display === 'block') {
                text2ImgArea.style.opacity = '0';
            } else if (modelViewerArea.style.display === 'block') {
                modelViewerArea.style.opacity = '0';
            } else if (segmentationArea.style.display === 'block') {
                segmentationArea.style.opacity = '0';
            } else if (imageDetailArea.style.display === 'block') {
                imageDetailArea.style.opacity = '0';
            } else if (yuyiArea.style.display === 'block') {
                yuyiArea.style.opacity = '0';
            }
            
            setTimeout(() => {
                text2ImgArea.style.display = 'none';
                modelViewerArea.style.display = 'none';
                segmentationArea.style.display = 'none';
                imageDetailArea.style.display = 'none';
                yuyiArea.style.display = 'none';
                navArea.style.display = 'block';
                clearInputs();
                loadingIndicator.style.display = 'none';
            }, 300);
        }

        // 滑块值实时显示
        function initSliderListeners() {
            const sliders = [
                { id: 'cfgWeight', valueId: 'cfgWeightValue', formatter: (v) => `当前值：${v}` },
                { id: 'temperature', valueId: 'temperatureValue', formatter: (v) => `当前值：${v}` },
                { id: 'cannyLow', valueId: 'cannyLowValue', formatter: (v) => `当前值：${v}` },
                { id: 'cannyHigh', valueId: 'cannyHighValue', formatter: (v) => `当前值：${v}` },
                { id: 'parallelSize', valueId: 'parallelSizeValue', formatter: (v) => `当前值：${v}` }
            ];

            sliders.forEach(({ id, valueId, formatter }) => {
                const slider = document.getElementById(id);
                const valueEl = document.getElementById(valueId);
                slider.addEventListener('input', () => {
                    valueEl.textContent = formatter(slider.value);
                    if (id === 'cannyLow') {
                        const cannyHigh = document.getElementById('cannyHigh');
                        if (parseInt(slider.value) >= parseInt(cannyHigh.value)) {
                            cannyHigh.value = parseInt(slider.value) + 1;
                            document.getElementById('cannyHighValue').textContent = `当前值：${cannyHigh.value}`;
                        }
                    }
                });
            });
        }

        // Canny图像预览与Base64转换
        let cannyImageBase64 = null;
        function previewCannyImage(event) {
            const file = event.target.files[0];
            if (!file) return;

            const reader = new FileReader();
            reader.onload = (e) => {
                document.getElementById('cannyPreview').src = e.target.result;
                cannyImageBase64 = e.target.result;
            };
            reader.readAsDataURL(file);
        }

        // 显示加载状态并执行生成逻辑
        function showLoading() {
            const promptInput = document.getElementById('promptInput');
            if (!promptInput.value.trim()) {
                promptInput.style.animation = 'none';
                setTimeout(() => {
                    promptInput.style.animation = 'shake 0.5s ease';
                }, 10);
                return;
            }
            
            loadingIndicator.style.display = 'block';
            imageGallery.innerHTML = '<p class="text-center w-100">正在生成图片，请稍候...</p>';
            statusEl.value = '正在生成图像，请稍候...';
            
            generateImage();
        }

        // 生成图像核心逻辑
        async function generateImage() {
            const prompt = document.getElementById('promptInput').value.trim();

            const params = {
                prompt: prompt,
                seed: document.getElementById('seedInput').value || null,
                cfg_weight: parseFloat(document.getElementById('cfgWeight').value),
                temperature: parseFloat(document.getElementById('temperature').value),
                canny_low: parseInt(document.getElementById('cannyLow').value),
                canny_high: parseInt(document.getElementById('cannyHigh').value),
                parallel_size: parseInt(document.getElementById('parallelSize').value),
                canny_image: cannyImageBase64
            };

            try {
                const response = await fetch('http://127.0.0.1:8000/generate-image', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify(params),
                    mode: 'cors'
                });

                if (!response.ok) throw new Error(`HTTP错误：${response.status}`);
                const data = await response.json();

                if (data.success && data.images.length > 0) {
                    imageGallery.innerHTML = '';
                    data.images.forEach((imgBase64, index) => {
                        const imgEl = document.createElement('img');
                        imgEl.src = imgBase64;
                        imgEl.className = 'gallery-img';
                        imgEl.alt = `生成结果 ${index + 1}`;
                        imageGallery.appendChild(imgEl);
                    });
                    statusEl.value = `生成成功！共生成${data.images.length}张图像`;
                } else {
                    throw new Error(data.message || '未返回有效图像');
                }
            } catch (error) {
                statusEl.value = `生成失败：${error.message}`;
                imageGallery.innerHTML = '';
                const errorImg = document.createElement('img');
                errorImg.src = 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="256" height="256" fill="%23dc3545" viewBox="0 0 16 16"%3E%3Cpath d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/%3E%3Cpath d="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 4.995z"/%3E%3C/svg%3E';
                errorImg.className = 'gallery-img';
                errorImg.alt = '生成错误';
                imageGallery.appendChild(errorImg);
            } finally {
                loadingIndicator.style.display = 'none';
            }
        }

        // 清除所有输入
        function clearInputs() {
            document.getElementById('promptInput').value = '';
            document.getElementById('seedInput').value = '';
            
            const defaultValues = {
                cfgWeight: 5,
                temperature: 1.0,
                cannyLow: 100,
                cannyHigh: 200,
                parallelSize: 2
            };
            Object.entries(defaultValues).forEach(([id, val]) => {
                const slider = document.getElementById(id);
                slider.value = val;
                document.getElementById(`${id}Value`).textContent = `当前值：${val}`;
            });
            
            const defaultPreview = 'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="100" height="100" fill="%23dee2e6" viewBox="0 0 16 16"%3E%3Cpath d="M11 2.5a2.5 2.5 0 1 1 .603 1.628l-6.718 3.12a2.499 2.499 0 0 1 0 1.504l6.718 3.12a2.5 2.5 0 1 1-.488.876l-6.718-3.12a2.5 2.5 0 1 1 0-3.256l6.718-3.12A2.5 2.5 0 0 1 11 2.5z"/%3E%3C/svg%3E';
            document.getElementById('cannyPreview').src = defaultPreview;
            document.getElementById('cannyImageInput').value = '';
            cannyImageBase64 = null;
            
            imageGallery.innerHTML = '';
            statusEl.value = '就绪';
        }

        // 保存所有生成的图像
        function saveAllImages() {
            const imgs = imageGallery.querySelectorAll('img');
            if (imgs.length === 0) {
                alert('没有可保存的图像！');
                return;
            }

            const timestamp = new Date().toISOString().replace(/[-:\.T]/g, '').slice(0, 14);
            imgs.forEach((img, index) => {
                const a = document.createElement('a');
                a.href = img.src;
                a.download = `ai-generated-${timestamp}-${index + 1}.png`;
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
            });

            statusEl.value = `已保存${imgs.length}张图像`;
        }

        // 3D模型查看器代码
        let scene, camera, renderer, controls;
        let currentModel = null;
        let autoRotate = false;
        let models = [];
        
        function initCeshiScene() {
            scene = new THREE.Scene();
            scene.background = new THREE.Color(0x1a1a2e);
            
            const viewer = document.getElementById('ceshi-model-viewer');
            camera = new THREE.PerspectiveCamera(75, viewer.clientWidth / viewer.clientHeight, 0.1, 1000);
            camera.position.z = 5;
            
            renderer = new THREE.WebGLRenderer({ antialias: true });
            renderer.setSize(viewer.clientWidth, viewer.clientHeight);
            document.getElementById('ceshi-model-viewer').appendChild(renderer.domElement);
            
            const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
            scene.add(ambientLight);
            
            const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
            directionalLight.position.set(5, 5, 5);
            scene.add(directionalLight);
            
            controls = new THREE.OrbitControls(camera, renderer.domElement);
            controls.enableDamping = true;
            controls.dampingFactor = 0.1;
            controls.autoRotate = false;
            
            window.addEventListener('resize', onCeshiWindowResize);
            
            function animate() {
                requestAnimationFrame(animate);
                if (autoRotate) {
                    scene.rotation.y += 0.005;
                }
                controls.update();
                renderer.render(scene, camera);
            }
            animate();
        }
        
        function onCeshiWindowResize() {
            const viewer = document.getElementById('ceshi-model-viewer');
            camera.aspect = viewer.clientWidth / viewer.clientHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(viewer.clientWidth, viewer.clientHeight);
        }
        
        function scanCeshiFolder(files) {
            const modelList = document.getElementById('model-list');
            const noModels = document.getElementById('no-models');
            models = [];
            
            modelList.innerHTML = '';
            
            Array.from(files).forEach(file => {
                const extension = file.name.split('.').pop().toLowerCase();
                if (['obj', 'gltf', 'glb'].includes(extension)) {
                    models.push(file);
                }
            });
            
            if (models.length === 0) {
                noModels.textContent = '未找到支持的3D模型文件';
                noModels.style.display = 'block';
                return;
            }
            
            noModels.style.display = 'none';
            
            models.forEach((file, index) => {
                const extension = file.name.split('.').pop().toLowerCase();
                let icon = '📁';
                
                if (extension === 'obj') icon = '🔷';
                else if (extension === 'gltf' || extension === 'glb') icon = '🔶';
                
                const modelItem = document.createElement('div');
                modelItem.className = 'ceshi-model-item';
                modelItem.innerHTML = `
                    <div class="ceshi-model-icon">${icon}</div>
                    <div class="ceshi-model-info">
                        <div class="ceshi-model-name">${file.name}</div>
                        <div class="ceshi-model-type">${extension.toUpperCase()} · ${(file.size / 1024).toFixed(1)} KB</div>
                    </div>
                `;
                
                modelItem.addEventListener('click', () => {
                    document.querySelectorAll('.ceshi-model-item').forEach(item => {
                        item.classList.remove('active');
                    });
                    modelItem.classList.add('active');
                    loadCeshiModel(file);
                });
                
                modelList.appendChild(modelItem);
                
                if (index === 0) {
                    modelItem.classList.add('active');
                    loadCeshiModel(file);
                }
            });
        }
        
        function initCeshiEvents() {
            document.getElementById('folder-btn').addEventListener('click', () => {
                document.getElementById('folder-input').click();
            });
            
            document.getElementById('folder-input').addEventListener('change', (e) => {
                const files = e.target.files;
                if (files.length > 0) {
                    scanCeshiFolder(files);
                }
            });
            
            document.getElementById('image-upload-btn').addEventListener('click', () => {
                document.getElementById('image-upload-input').click();
            });
            
            document.getElementById('image-upload-input').addEventListener('change', (e) => {
                const file = e.target.files[0];
                if (!file) return;
                
                if (!file.type.match('image.*')) {
                    alert('请选择图片文件！');
                    return;
                }
                
                const loadingElement = document.getElementById('loading');
                loadingElement.style.display = 'block';
                
                setTimeout(() => {
                    alert('图片上传成功！图生3D功能正在开发中，将使用示例模型展示效果。');
                    
                    const loader = new THREE.GLTFLoader();
                    loader.load(
                        'https://threejs.org/examples/models/gltf/LittlestTokyo.glb',
                        (gltf) => {
                            if (currentModel) {
                                scene.remove(currentModel);
                            }
                            
                            currentModel = gltf.scene;
                            scene.add(currentModel);
                            
                            currentModel.scale.set(0.01, 0.01, 0.01);
                            currentModel.position.set(0, -1, 0);
                            
                            updateCeshiModelInfo(file, currentModel, true);
                            
                            loadingElement.style.display = 'none';
                            
                            alert('3D模型生成成功！');
                        }, undefined, function(error) {
                            console.error('加载模型时出错:', error);
                            loadingElement.style.display = 'none';
                            alert('生成3D模型时出错: ' + error);
                        });
                }, 2000);
            });
            
            document.getElementById('reset-view').addEventListener('click', () => {
                controls.reset();
            });
            
            document.getElementById('toggle-rotate').addEventListener('click', () => {
                autoRotate = !autoRotate;
                document.getElementById('toggle-rotate').style.background = autoRotate ? 
                    'rgba(74, 144, 226, 0.7)' : 'rgba(0, 0, 0, 0.7)';
            });
            
            document.getElementById('model-info').addEventListener('click', () => {
                const infoPanel = document.getElementById('info-panel');
                infoPanel.style.display = infoPanel.style.display === 'none' ? 'block' : 'none';
            });
            
            document.getElementById('close-info').addEventListener('click', () => {
                document.getElementById('info-panel').style.display = 'none';
            });
            
            setTimeout(() => {
                if (models.length === 0) {
                    document.getElementById('no-models').textContent = 
                        '点击"选择3D模型文件夹"按钮开始扫描，或使用"上传图片模式"从图片生成3D模型';
                }
            }, 1000);
        }
        
        function updateCeshiModelInfo(file, object, isFromImage = false) {
            const infoPanel = document.getElementById('info-panel');
            const modelDetails = document.getElementById('model-details');
            
            const box = new THREE.Box3().setFromObject(object);
            const size = box.getSize(new THREE.Vector3());
            
            if (isFromImage) {
                modelDetails.innerHTML = `
                    <p><strong>源图片:</strong> ${file.name}</p>
                    <p><strong>生成模型格式:</strong> GLTF</p>
                    <p><strong>模型尺寸:</strong> ${size.x.toFixed(2)} × ${size.y.toFixed(2)} × ${size.z.toFixed(2)}</p>
                    <p><strong>文件大小:</strong> ${(file.size / 1024).toFixed(1)} KB</p>
                `;
            } else {
                const extension = file.name.split('.').pop().toUpperCase();
                modelDetails.innerHTML = `
                    <p><strong>文件名:</strong> ${file.name}</p>
                    <p><strong>格式:</strong> ${extension}</p>
                    <p><strong>模型尺寸:</strong> ${size.x.toFixed(2)} × ${size.y.toFixed(2)} × ${size.z.toFixed(2)}</p>
                    <p><strong>文件大小:</strong> ${(file.size / 1024).toFixed(1)} KB</p>
                `;
            }
        }
        
        function loadCeshiModel(file) {
            const loadingElement = document.getElementById('loading');
            loadingElement.style.display = 'block';
            
            if (currentModel) {
                scene.remove(currentModel);
            }
            
            const extension = file.name.split('.').pop().toLowerCase();
            const objectUrl = URL.createObjectURL(file);
            
            if (extension === 'obj') {
                const objLoader = new THREE.OBJLoader();
                objLoader.load(
                    objectUrl,
                    (object) => {
                        currentModel = object;
                        scene.add(currentModel);
                        
                        const box = new THREE.Box3().setFromObject(object);
                        const center = box.getCenter(new THREE.Vector3());
                        object.position.sub(center);
                        
                        updateCeshiModelInfo(file, object);
                        
                        loadingElement.style.display = 'none';
                    },
                    undefined,
                    (error) => {
                        console.error('加载OBJ模型时出错:', error);
                        loadingElement.style.display = 'none';
                        alert('加载模型时出错: ' + error.message);
                    }
                );
            } else if (extension === 'gltf' || extension === 'glb') {
                const gltfLoader = new THREE.GLTFLoader();
                gltfLoader.load(
                    objectUrl,
                    (gltf) => {
                        currentModel = gltf.scene;
                        scene.add(currentModel);
                        
                        const box = new THREE.Box3().setFromObject(currentModel);
                        const center = box.getCenter(new THREE.Vector3());
                        currentModel.position.sub(center);
                        
                        updateCeshiModelInfo(file, currentModel);
                        
                        loadingElement.style.display = 'none';
                    },
                    undefined,
                    (error) => {
                        console.error('加载GLTF模型时出错:', error);
                        loadingElement.style.display = 'none';
                        alert('加载模型时出错: ' + error.message);
                    }
                );
            }
        }
    </script>
</body>
</html>